home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Pascal Super Library
/
Pascal Super Library (CW International)(1997).bin
/
PARSER
/
KPARS_00
/
KSTRING.PAS
< prev
Wrap
Pascal/Delphi Source File
|
1993-09-02
|
49KB
|
1,599 lines
{$A-}
{$B-}
{$D-}
{$E-}
{$F+}
{$I-}
{$L-}
{$N-}
{$O+}
{$R-} {Range checking off}
{$S-}
{$V-}
UNIT Kstring;
{+H
---------------------------------------------------------------------------
File - Kstring.PAS
Copyright (c) Klingon Software Services 1987..1993 except where noted.
All rights reserved.
Author - Keith S. Brown (except where otherwise noted)
Surface mail: Email:
K.Brown
2437 Bay Area Blvd #20
Houston, TX 77058 (USA) Voice:713-486-6765
Purpose - String and character manipulation routines.
Language - Borland International's Turbo Pascal V:4.x+ for MS-DOS
Requires - Turbo Power Professional's TPSTRING.PAS unit.
Reference - See documentation of individual proc/funct.
Revised - 1987.xxxx (KSB) Wrote initial version.
- 1991.0613 (KSB) Added ArrayToString. Renamed StringConvert to
StringToArray. Added LastChar, NextPos, RightPos, Chop, ChopCh, Plural, and InSet.
- 1991.0625 (KSB) Added WeightToLbOzStr
- 1991.0828 (KSB) Added Replicate function.
- 1991.0904 (KSB) Fixed DoubleCheck.
- 1992.0330 (KSB) Added character test functions.
- 1992.0407 (KSB) Added StringToReal function.
- 1992.0423 (KSB) Mod'd Long2LStr, StringToLong, StringToReal, DollarsToPennies.
- 1992.0930 (KSB) Added ChOfStr, Squeeze, Squeeze_ANP, SqueezeAN, Reverse, IsPunct, IsExtended.
---------------------------------------------------------------------------}
INTERFACE
USES
TPstring; {from TurboPower Professional V:5.07}
{------------------------------
{Trimming & padding}
{Fix functions trim before padding}
{}FUNCTION Fix(s:STRING; len:BYTE):STRING;
{}FUNCTION FixCh(s:STRING; Ch:CHAR; len:BYTE):STRING;
{}FUNCTION LeftFix(s:STRING; len:BYTE):STRING;
{}FUNCTION LeftFixCh(s:STRING; Ch:CHAR; len:BYTE):STRING;
{Chop functions trimright before padding}
{}FUNCTION Chop(s:STRING; len:BYTE):STRING;
{}FUNCTION ChopCh(s:STRING; Ch:CHAR; len:BYTE):STRING;
{------------------------------
{Parsing, splitting, etc}
{}FUNCTION Before(source,target:STRING):STRING;
{}FUNCTION After(source,target:STRING):STRING;
{}FUNCTION Parse(VAR source:STRING; separator:STRING):STRING;
{}FUNCTION DoubleCheck(s:STRING; Ch:CHAR):STRING;
{}FUNCTION Replace(s,substr,newstr:STRING):STRING;
{}FUNCTION ReplaceAll(s,substr,newstr:STRING):STRING;
{}FUNCTION OverWrite(s:STRING; INDEX:BYTE; subStr:STRING): STRING;
{}FUNCTION LastChar(s:STRING):CHAR;
{}FUNCTION NextPos(substr,s: STRING; lastpos:BYTE; ignorecase:BOOLEAN):BYTE;
{}FUNCTION RightPos(substr,s:STRING; lastPos:BYTE; ignoreCase:BOOLEAN):BYTE;
{}FUNCTION Replicate(s:STRING; Len:BYTE):STRING;
{}FUNCTION SeekCharRange(s: STRING; ch1,ch2:CHAR; StartPos:BYTE):BYTE;
{}FUNCTION ChOfStr(s:STRING; INDEX:BYTE):CHAR;
{}FUNCTION StrEnd(s:STRING):BYTE;
{}FUNCTION Squeeze(s:STRING):STRING; {leaves alphanums, punctuation}
{}FUNCTION Squeeze_ANP(s:STRING):STRING; {leaves alphanums, '.' & '_'}
{}FUNCTION SqueezeAN(s:STRING):STRING; {leaves alphanums only}
{}FUNCTION Reverse(s:STRING):STRING; {reverses S}
{------------------------------
{formatting}
{}FUNCTION PhoneStr(phone:STRING):STRING;
{}FUNCTION FullPhoneStr(phone:STRING):STRING;
{}FUNCTION PennyStr(Pennies:LongINT; MaxLen:BYTE; DollarSign:BOOLEAN):STRING;
{}FUNCTION Plural(num:LongINT; thing:STRING):STRING;
{}FUNCTION Cap1stChar(s:STRING):STRING;
{}FUNCTION Long2LStr(L:LongINT; width:BYTE):STRING;
{}FUNCTION BankStr(pennies:LongINT):STRING;
{}FUNCTION Long2Text(L:LongINT):STRING;
{}FUNCTION WeightToLbOzStr(w:LongINT):STRING;
{------------------------------
{type conversion}
{}FUNCTION StringToLong(s:STRING):LongINT;
{}PROCEDURE StringToArray(StrP:STRING; VAR CharArrayP; Len: BYTE);
{}FUNCTION ArrayToString(VAR CharArrayP; start:WORD; Len:BYTE):STRING;
{}FUNCTION StringToReal(s:STRING):REAL;
{}FUNCTION DollarsToPennies(s:STRING):LongINT;
{------------------------------
{Pattern matching}
{}FUNCTION Matches(s,pattern:STRING):BOOLEAN;
{}FUNCTION IsAfter(s1,s2,s:STRING):BOOLEAN;
{}FUNCTION IsBefore(s1,s2,s:STRING):BOOLEAN;
{}FUNCTION Indented(s:STRING):BYTE;
{------------------------------
{character tests}
{}FUNCTION IsLetter(c:CHAR):BOOLEAN; {T if c is 'A'..'Z','a'..'z'}
{}FUNCTION IsLower(c:CHAR):BOOLEAN; {T if c is 'a'..'z'}
{}FUNCTION IsUpper(c:CHAR):BOOLEAN; {T if c is 'A'..'Z'}
{}FUNCTION IsDigit(c:CHAR):BOOLEAN; {T if c is '0'..'9'}
{}FUNCTION IsHexDigit(c:CHAR):BOOLEAN; {T if c is hex digit}
{}FUNCTION IsAlphaNum(c:CHAR):BOOLEAN; {T if c is letter or number}
{}FUNCTION IsAscii(c:CHAR):BOOLEAN; {T if c is #000..#127}
{}FUNCTION IsCntrl(c:CHAR):BOOLEAN; {T if c is #000..#021,#127}
{}FUNCTION IsExtended(c:CHAR):BOOLEAN; {T if c is #128..#255}
{}FUNCTION IsPrint(c:CHAR):BOOLEAN; {T if c is #032..#126}
{}FUNCTION IsPunct(c:CHAR):BOOLEAN; {T if c is a punctuation char}
{}FUNCTION IsSpace(c:CHAR):BOOLEAN; {T if c is space,tab,CR,LF,VT,FF}
{------------------------------
{other}
{}FUNCTION InSet(VAR someSet; VAR setMember):BOOLEAN;
{}FUNCTION CountOf(s:STRING; cs:CharSet):BYTE;
{====================================================================}
IMPLEMENTATION
{------------------------------
{Trimming & Padding}
{}FUNCTION Fix(s:STRING; len:BYTE):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Remove all leading and trailing white space from S.
Declaration - Fix(s:STRING; len:BYTE)
Result type - string.
Remarks - If the length of S is greater than LEN then truncate it to
LEN, else right pad with blanks to length LEN.
---------------------------------------------------------------------------}
VAR
L : BYTE ABSOLUTE s;
BEGIN
s := Trim(s);
IF L > len THEN
L := len
ELSE
s := Pad(s,len);
Fix:= s;
{}END {Fix};
{}FUNCTION FixCh(s:STRING; Ch:CHAR; len:BYTE):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Remove all leading and trailing white space from S.
Declaration - FixCh(s:STRING; Ch:CHAR; len:BYTE)
Result type - string.
Remarks - If the length of S is greater than LEN then truncate it to
LEN, else right pad with it with Ch to length LEN.
---------------------------------------------------------------------------}
VAR
L : BYTE ABSOLUTE s;
BEGIN
s := Trim(s);
IF L > len THEN
L := len
ELSE
s := PadCh(s,Ch,len);
FixCh := s;
{}END {FixCh};
{}FUNCTION LeftFix(s:STRING; len:BYTE):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Remove all leading and trailing white space from S.
Declaration - LeftFix(s:STRING; len:BYTE)
Result type - string.
Remarks - If the length of S is greater than LEN then truncate it to
LEN, else left pad with blanks to length LEN.
---------------------------------------------------------------------------}
VAR
L : BYTE ABSOLUTE s;
BEGIN
s := Trim(s);
IF L > len THEN
L := len
ELSE
s := LeftPad(s,len);
LeftFix:= s;
{}END {LeftFix};
{}FUNCTION LeftFixCh(s:STRING; Ch:CHAR; len:BYTE):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Remove all leading and trailing white space from S.
Declaration - LeftFixCh(s:STRING; Ch:CHAR; len:BYTE)
Result type - string.
Remarks - If the length of S is greater than LEN then truncate it to
LEN, else left pad with it with Ch to length LEN.
---------------------------------------------------------------------------}
VAR
L : BYTE ABSOLUTE s;
BEGIN
s := Trim(s);
IF L > len THEN
L := len
ELSE
s := LeftPadCh(s,Ch,len);
LeftFixCh := s;
{}END {LeftFixCh};
{}FUNCTION Chop(s:STRING; len:BYTE):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Truncate S from the right if S is longer than LEN.
Declaration - Chop(s:STRING; len:BYTE)
Result type - string.
Remarks - Pad S with blanks if S is shorter than LEN.
---------------------------------------------------------------------------}
VAR
L : BYTE ABSOLUTE s;
BEGIN
IF L > len THEN
L := len
ELSE
s := Pad(s,len);
Chop := s;
{}END {Chop};
{}FUNCTION ChopCh(s:STRING; Ch:CHAR; len:BYTE):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Truncate S from the right if S is longer than LEN.
Declaration - ChopCh(s:STRING; Ch:CHAR; len:BYTE)
Result type - string.
Remarks - Pad S with CH characters if S is shorter than LEN.
---------------------------------------------------------------------------}
VAR
L : BYTE ABSOLUTE s;
BEGIN
IF L > len THEN
L := len
ELSE
s := PadCh(s,Ch,len);
ChopCh := s;
{}END {ChopCh};
{------------------------------
{Parsing, splitting, etc.}
{}FUNCTION Before(source,target:STRING):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Returns all of the source string up to but not including
the first occurance of the target string.
Declaration - Before(source,target:STRING)
Result type - string.
Author - Dick Pountain. Byte; Dec 1988; Pp.307-314
---------------------------------------------------------------------------}
BEGIN
IF Pos(target,source) = 0 THEN
Before := source
ELSE
Before := Copy(source,1,Pred(Pos(target,source)));
{}END {Before};
{}FUNCTION After(source,target:STRING):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Returns all of the source string that follows (but does not
include) the first occurance of the target string.
Declaration - After(source,target:STRING)
Result type - string.
Author - Dick Pountain. Byte; Dec 1988; Pp.307-314
---------------------------------------------------------------------------}
BEGIN
IF Pos(target,source) = 0 THEN
After := ''
ELSE
After := Copy(source,Pos(target,source)+Length(target),Length(source));
{}END {After};
{}FUNCTION Parse(VAR source:STRING; separator:STRING):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Treats SOURCE as a stream of tokens, separated by a string
delimiter called SEPARATOR. Each call to PARSE returns a
single new token from the stream. When the tokens are all
used up, it continues to return null strings.
Warning - This function modifies its arguments, ie., it lacks idempotency.
Declaration - Parse(VAR source:STRING; separator:STRING)
Result type - string.
Author - Dick Pountain. Byte; Dec 1988; Pp.307-314
---------------------------------------------------------------------------}
BEGIN
Parse := Before(source,separator);
source:= After(source,separator);
{}END {Parse};
{}FUNCTION DoubleCheck(s:STRING; Ch:CHAR):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Removes all multiple separators from the input string S.
Declaration - DoubleCheck(s:STRING; Ch:CHAR)
Result type - string.
Author - S. Balch. Byte; Apr 1989; Pp.40
Revised - 1991.0903 (KSB) Added check for ch+ch to prevent ch from
being appended if ch+ch is not found.
---------------------------------------------------------------------------}
BEGIN
IF Pos(ch+ch,s) > 0 THEN
REPEAT
s := Before(s,ch+ch)+ch+After(s,ch+ch);
UNTIL After(s,Ch+Ch) = '';
DoubleCheck := s;
{}END {DoubleCheck};
{}FUNCTION Replace(s,substr,newstr:STRING):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Replace the first occurance of SUBSTR found in S with NEWSTR
Declaration - Replace(s,substr,newstr:STRING)
Result type - string.
---------------------------------------------------------------------------}
BEGIN
IF Pos(subStr,s)>0 THEN
Replace := Before(s,substr)+newStr+After(s,subStr)
ELSE
Replace := s;
{}END {Replace};
{}FUNCTION ReplaceAll(s,substr,newstr:STRING):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Replace all occurances of SUBSTR found in S with NEWSTR.
Declaration - ReplaceAll(s,substr,newstr:STRING)
Result type - string.
---------------------------------------------------------------------------}
BEGIN
WHILE Pos(subStr,s)>0 DO
s := Replace(s,substr,newstr);
ReplaceAll := s;
{}END {ReplaceAll};
{}FUNCTION OverWrite(s:STRING; INDEX:BYTE; subStr:STRING): STRING;
{+H
---------------------------------------------------------------------------
Purpose - Overwrites string S with substring SUBSTR starting at position
INDEX of S. If INDEX is greater than the length of S, S is
is blank extended. Max returned string length is 255.
Declaration - OverWrite(s:STRING; index:BYTE; subStr:STRING)
Result type - string.
---------------------------------------------------------------------------}
VAR
L1 : BYTE ABSOLUTE s; { length of S }
L2 : BYTE ABSOLUTE subStr; { length of substring }
i : BYTE; { substring index }
BEGIN
IF INDEX > L1 THEN
s := s + CharStr(' ',Pred(INDEX-L1)) + subStr
ELSE BEGIN
i := 1;
WHILE (INDEX < 256) AND (i <= L2) DO BEGIN
s[INDEX] := SubStr[i];
Inc(INDEX); Inc(i);
END {WHILE};
IF Pred(INDEX) > L1 THEN
s[0] := Chr(Pred(INDEX));
END {IF};
OverWrite := s;
{}END {OverWrite};
{}FUNCTION LastChar(s:STRING):CHAR;
{+H
---------------------------------------------------------------------------
Purpose - Returns the last character of a string.
Declaration - LastChar(s:STRING)
Result type - char.
---------------------------------------------------------------------------}
BEGIN
IF s = '' THEN
LastChar := #0
ELSE
LastChar := s[Length(s)];
{}END {LastChar};
{}FUNCTION NextPos(substr,s:STRING; lastpos:BYTE; ignorecase:BOOLEAN):BYTE;
{+H
---------------------------------------------------------------------------
Purpose - Searches for a substring in a string starting at the 'lastpos'
character in 's'. If 'ignorecase' is True, then both strings
are first converted to uppercase. Returns the location of the
next occurrence of 'substr' within 's' or 0 if not found
'lastpos' need not be a valid position. Char's to the left of
'lastpos' will not be examined.
Declaration - NextPos(substr,s:STRING; lastpos:BYTE; ignorecase:BOOLEAN)
Result type - byte.
---------------------------------------------------------------------------}
VAR
npos : BYTE;
i : BYTE;
BEGIN
s := Copy(s,Succ(lastpos),Length(s)-lastpos); {Trim the search string}
IF ignorecase THEN BEGIN {If case is to be ignored,}
s := StUpCase(s); { then convert the strings}
subStr := StUpCase(subStr); { to uppercase}
END {IF};
npos := Pos( substr, s );
IF npos > 0 THEN
npos := npos + lastpos;
Nextpos := npos;
{}END {NextPos};
{}FUNCTION RightPos(substr,s:STRING; lastPos:BYTE; ignoreCase:BOOLEAN):BYTE;
{+H
---------------------------------------------------------------------------
Purpose - Searches for a substring in a string starting at the 'lastpos'
character in 's' & working backwards towards the beginning of
the string. If the 'ignorecase' is True, then both strings are
first converted to uppercase. Returns the location of the next
(right) occurrence of 'substr' within 's' or 0 if not found.
'lastpos' need not be a valid position. Characters to the
right of 'lastpos' will not be examined (as the head of the
substring).
Declaration - RightPos(substr,s:STRING; lastPos:BYTE; ignoreCase:BOOLEAN)
Result type - byte.
---------------------------------------------------------------------------}
VAR
npos : BYTE;
i : BYTE;
temp : STRING;
BEGIN
temp := Copy( s, 1, lastPos); {Trim the search string}
IF ignorecase THEN BEGIN {If case is to be ignored,}
temp := StUpCase(temp); { then convert the strings}
substr := StUpCase(substr); { to uppercase}
END {IF};
npos := 0;
i := lastPos;
WHILE (npos=0) AND (i>0) DO BEGIN
s := Copy(temp,i,lastPos);
npos := Pos( substr, s );
Dec(i);
END {WHILE};
Rightpos := npos+i;
{}END {RightPos};
{}FUNCTION Replicate(s:STRING; Len:BYTE):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Return a string of length LEN filled with S.
Declaration - Replicate(s:STRING; Len:BYTE)
Result type - string.
---------------------------------------------------------------------------}
VAR
t : STRING;
L : BYTE ABSOLUTE s;
m : BYTE ABSOLUTE t;
BEGIN
CASE L OF
0 : Replicate := ''; {zero length pattern}
1 : Replicate := CharStr(s[1],Len); {1 char pattern}
ELSE
{multiple char pattern}
t := '';
WHILE m < Len DO
t := t + s;
t[0] := Chr(Len);
Replicate := t;
END {CASE};
{}END {Replicate};
{}FUNCTION SeekCharRange(s: STRING; ch1,ch2:CHAR; StartPos:BYTE):BYTE;
{+H
---------------------------------------------------------------------------
Purpose - Searches for the first of a range of characters that lie
between CH1 and CH2 (inclusive) in S.
Declaration - SeekCharRange(s: STRING; ch1,ch2:CHAR; StartPos:BYTE)
Result type - byte.
Remarks - If STARTPOS is greater than 1, then only that portion of S
to the right of STARTPOS (inclusive) will be examined.
---------------------------------------------------------------------------}
VAR
L : BYTE ABSOLUTE s;
sPos : WORD;
Found: BOOLEAN;
BEGIN
IF StartPos <= L THEN BEGIN
sPos := StartPos;
REPEAT
Found := (s[sPos] >= Ch1) AND (s[sPos] <= Ch2);
Inc(sPos);
UNTIL Found OR (sPos > L);
IF Found THEN
SeekCharRange := Pred(sPos)
ELSE
SeekCharRange := 0;
END ELSE
SeekCharRange := 0;
{}END {SeekCharRange};
{}FUNCTION ChOfStr(s:STRING; INDEX:BYTE):CHAR;
{+H
---------------------------------------------------------------------------
Purpose - Return the INDEX'th character of S.
Declaration - ChOfStr(s:STRING; index:BYTE)
Result type - char.
Remarks - S is a string-type expression. INDEX is an integer-type
expression. The result of type char is the INDEX'th character
of S if INDEX is between 1 and Length(S) inclusive, otherwise
it is an ASCII zero.
---------------------------------------------------------------------------}
BEGIN
IF (INDEX > Length(s)) THEN
ChOfStr := #0
ELSE
ChOfStr := s[INDEX];
{}END {ChOfStr};
{}FUNCTION StrEnd(s:STRING):BYTE;
{+H
---------------------------------------------------------------------------
Purpose - Returns the position of the last non-white space char in S.
---------------------------------------------------------------------------}
VAR
L : BYTE ABSOLUTE s;
BEGIN
WHILE (L>0) AND (s[L] IN [#$00..#$20]) DO
Dec(L);
StrEnd := L;
{}END {StrEnd};
{}FUNCTION Squeeze(s:STRING):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Squeeze out all control characters & white space from a string.
Declaration - Squeeze(s:STRING)
Result type - string.
---------------------------------------------------------------------------}
VAR
i : INTEGER;
t : STRING;
ch : SET OF CHAR;
BEGIN
t := '';
ch:= [#0..#32,#127..#255];
FOR i := 1 TO Length(s) DO
IF NOT (s[i] IN ch) THEN
t := t + s[i];
Squeeze := t;
{}END {Squeeze};
{}FUNCTION Squeeze_ANP(s:STRING):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Squeeze out all characters except letters, numbers, periods
and underscores from a string.
Declaration - Squeeze_ANP(s:STRING)
Result type - string.
---------------------------------------------------------------------------}
VAR
i : INTEGER;
t : STRING;
ch : SET OF CHAR;
BEGIN
t := '';
ch:= ['.','_','0'..'9','A'..'Z','a'..'z'];
FOR i := 1 TO Length(s) DO
IF s[i] IN ch THEN
t := t + s[i];
Squeeze_ANP := t;
{}END {Squeeze_ANP};
{}FUNCTION SqueezeAN(s:STRING):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Squeeze out all non alpha numeric characters from a string.
Declaration - SqueezeAN(s:STRING)
Result type - string.
---------------------------------------------------------------------------}
VAR
i : INTEGER;
t : STRING;
ch : SET OF CHAR;
BEGIN
t := '';
ch:= ['0'..'9','A'..'Z','a'..'z'];
FOR i := 1 TO Length(s) DO
IF (s[i] IN ch) THEN
t := t + s[i];
SqueezeAN := t;
{}END {SqueezeAN};
{}FUNCTION Reverse(s:STRING):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Reverse the characters in a string.
Declaration - Reverse(s:STRING)
Result type - string.
---------------------------------------------------------------------------}
VAR
i : INTEGER;
t : STRING;
ch : SET OF CHAR;
BEGIN
t := '';
FOR i := 1 TO Length(s) DO
t := s[i] + t;
Reverse := t;
{}END {Reverse};
{------------------------------
{Formatting}
{}FUNCTION PhoneStr(phone:STRING):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Converts a compressed phone number to a formatted string
containing just the local exchange.
Declaration - PhoneStr(phone:STRING)
Result type - string.
Example - s := PhoneStr('7133332655'); s contains '333-2655'
---------------------------------------------------------------------------}
BEGIN
Phone := Copy(Phone,Length(Phone)-6,7);
PhoneStr := Copy(Phone,1,3)+'-'+Copy(phone,4,4);
{}END {PhoneStr};
{}FUNCTION FullPhoneStr(phone:STRING):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Converts a compressed phone number to a formatted string
containing the full phone number.
Declaration - FullPhoneStr(phone:STRING)
Result type - string.
Example - s := FullPhoneStr('7133332655'); s contains '(713)333-2655'
---------------------------------------------------------------------------}
BEGIN
FullPhoneStr := '('+Copy(Phone,1,3)+')'+Copy(phone,4,3)+'-'+Copy(phone,7,4);
{}END {FullPhoneStr};
{}FUNCTION PennyStr(Pennies:LongINT; MaxLen:BYTE; DollarSign:BOOLEAN):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Convert a money amount (stored as the number of cents) to
the standard US dollar convention.
Declaration - PennyStr(Pennies:LongINT; MaxLen:BYTE; DollarSign:BOOLEAN)
Result type - string.
Example - s := PennyStr(23452,8,TRUE); s contains ' $234.52'
---------------------------------------------------------------------------}
CONST {....^....1....^....2}
mask = '#################.##';
{2....^....1....^....}
VAR
r : FLOAT;
p : BYTE;
m,t : STRING;
BEGIN
IF DollarSign THEN
Dec(MaxLen);
p := 21 - MaxLen;
r := Pennies / 100.0;
m := Copy(mask,p,MaxLen);
IF DollarSign THEN
m := '$'+m;
t := TPString.Form(m,r);
PennyStr := t;
{}END {PennyStr};
{}FUNCTION Cap1stChar(s:STRING):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Capitalize the first letter in each occurance of a substring,
where substrings are defined by the delimiters <space>,
<comma>, <period>, <tab>, <(> and <->.
Declaration - Cap1stChar(s:STRING)
Result type - string.
Revised - 1988.0822 (KSB) Added <(> to delimeters.
- 1992.0930 (KSB) Added <-> to delimeters.
---------------------------------------------------------------------------}
VAR
i : WORD;
isDelimit : BOOLEAN;
wasDelimit: BOOLEAN;
BEGIN
wasDelimit := TRUE;
FOR i := 1 TO Length(s) DO BEGIN
isDelimit := (s[i] IN [' ',',','.',#09,'(','-']); {1992.0930}
IF wasDelimit AND (NOT isDelimit) THEN
s[i] := UpCase(s[i])
ELSE
s[i] := LoCase(s[i]);
wasDelimit := isDelimit;
END {FOR};
Cap1stChar := s;
{}END {Cap1stChar};
{}FUNCTION Plural(num:LongINT; thing:STRING):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Convert a LongINT/Word/Integer/Byte/ShortInt to a string that
that is followed by the pluralized descriptor THING.
Declaration - Plural(num:LongINT; thing:STRING)
Result type - string.
Example - s := Plural(0,'baby'); s contains 'no babies'
s := Plural(1,'bunny'); s contains '1 bunny'
s := Plural(2,'dollar'); s contains '2 dollars'
---------------------------------------------------------------------------}
VAR
temp : STRING[10];
ch : CHAR;
{}{}FUNCTION Plurals:STRING;
BEGIN
ch := LastChar(thing);
IF UpCase(ch) = 'Y' THEN
Plurals := Copy(thing,1,Length(thing)-1)+'ies'
ELSE
Plurals := thing+'s'
{}{}END {Plurals};
BEGIN
Str(num,temp);
CASE num OF
0 : Plural := 'No '+Plurals;
1 : Plural := '1 '+thing;
ELSE
Plural := temp+' '+Plurals;
END {CASE};
{}END {Plural};
{}FUNCTION Long2LStr(L:LongINT; width:BYTE):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Convert a LongINT/Word/Integer/Byte/ShortInt to a string of
at least WIDTH character, left padded with blanks if required.
Declaration - Long2LStr(L:LongINT; width:BYTE)
Result type - string.
Revised - 1992.0423 (KSB) Used Str to convert L to S.
---------------------------------------------------------------------------}
VAR
s : STRING;
BEGIN
Str(L,s);
Long2LStr := LeftPad(s,width);
{}END {Long2LStr};
{}FUNCTION Long2Text(L:LongINT):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Convert a LongINT/Word/Integer/Byte/ShortInt to a text string
Long2Text always returns a positive value.
Declaration - Long2Text(L:LongINT)
Result type - string.
Example - s := Long2Text(25); s contains "Twenty five"
---------------------------------------------------------------------------}
CONST
ones : ARRAY[0..9]OF STRING[5]=
('zero','one','two','three','four','five','six','seven','eight','nine');
tenty: ARRAY[10..19]OF STRING[9] =
('ten','eleven','twelve','thirteen','fourteen','fifteen','sixteen','seventeen','eighteen','nineteen');
tens : ARRAY[2..9]OF STRING[7]=
('twenty','thirty','fourty','fifty','sixty','seventy','eighty','ninety');
hundred = ' hundred';
thousand = ' thousand';
million = ' million';
billion = ' billion';
{}{}FUNCTION UpTo100(s:STRING):STRING;
VAR
t : STRING;
L : BYTE ABSOLUTE s;
BEGIN
t := '';
REPEAT
CASE L OF
1 :
IF s <> '0' THEN
t := t + ones[StringToLong(s)]
ELSE
IF t = '' THEN
t := t + ones[StringToLong(s)];
2 :
CASE s[1] OF
'0' : ;
'1' :
BEGIN
t := t + tenty[StringToLong(s)] + ' ';
Delete(s,1,1);
END {BEGIN};
ELSE
t := t + tens[StringToLong(s[1])] + ' ';
END {CASE};
3 : t := t + ones[StringToLong(s[1])] + hundred + ' ';
END {CASE};
Delete(s,1,1);
UNTIL L = 0;
UpTo100 := Trim(t);
{}{}END {UpTo100};
VAR
s,t,u: STRING;
Len : BYTE ABSOLUTE s;
i : BYTE;
BEGIN
s := Long2Str(Abs(L));
t := '';
REPEAT
CASE Len OF
0..3 : u := '';
4..6 : u := thousand;
7..9 : u := million;
10..12 : u := billion;
END {CASE};
i := Len MOD 3;
IF (Len > 0) AND (i = 0) THEN
i := 3;
t := t + UpTo100(Copy(s,1,i))+u + ' ';
Delete(s,1,i);
UNTIL Len=0;
Long2Text := Trim(t);
{}END {Long2Text};
{}FUNCTION BankStr(pennies:LongINT):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Convert the number of pennies to a text description. BankStr
always returns a positive value.
Declaration - BankStr(pennies:LongINT)
Result type - string.
Example - s := BankStr(45235);
s contains "Four hundred fifty two dollars and thirty five cents"
---------------------------------------------------------------------------}
VAR
s,t : STRING;
L : BYTE ABSOLUTE s;
BEGIN
pennies := Abs(pennies);
s := Long2Str(pennies);
t := Copy(s,L-1,2);
s := Copy(s,1,L-2);
BankStr := Long2Text(StringToLong(s))+' dollars and '+
Long2Text(StringToLong(t))+' cents';
{}END {BankStr};
{}FUNCTION WeightToLbOzStr(w:LongINT):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Display W (total ounces) in one of the following formats,
depending on the magnitude of W:
xxx:xx for 0 to 15,999 ounces
xxxxx# for 16,000 to 1,599,991 ounces
xxxxxT for 1,599,992 to 2,147,483,647 ounces
Declaration - WeightToLbOzStr(w:LongINT)
Result type - string.
Revised - 1991.0414 (KSB) Wrote Initial Version.
- 1991.0624 (KSB) Padded ounces with leading zeros.
---------------------------------------------------------------------------}
VAR
ton : WORD;
Lb,oz: WORD;
BEGIN
Lb := w DIV 16;
oz := w - (Lb*16);
IF w < 16 THEN
WeightToLbOzStr := ' 0:'+ReplaceAll(Long2LStr(w,2),' ','0')
ELSE
IF w < 16000 THEN
WeightToLbOzStr := Long2LStr(Lb,3)+':'+ReplaceAll(Long2LStr(oz,2),' ','0')
ELSE
IF w < 1599992 THEN
WeightToLbOzStr := Long2LStr(lb,5)+'#'
ELSE
WeightToLbOzStr := Long2LStr((Lb DIV 2000),5)+'T'
{}END {WeightToLbOzStr};
{------------------------------
{Type Conversion}
{}FUNCTION StringToLong(s:STRING):LongINT;
{+H
---------------------------------------------------------------------------
Purpose - Convert a string representation of a number to a value.
Declaration - StringToLong(s:STRING)
Revised - 1990.1216 (KSB) Wrote initial version.
- 1992.0423 (KSB) Rewrote without reference to TP calls.
---------------------------------------------------------------------------}
VAR
L : LongINT;
len : BYTE ABSOLUTE s;
c : INTEGER;
BEGIN
WHILE s[len] = ' ' DO
Dec(len);
Val(s,L,c);
IF c <> 0 THEN
L := 0;
StringToLong := L;
{}END {StringToLong};
{}PROCEDURE StringToArray(StrP:STRING; VAR CharArrayP; Len: BYTE);
{+H
---------------------------------------------------------------------------
Purpose - converts a string to a character array of LEN.
Declaration - StringToArray(StrP:STRING; VAR CharArrayP; Len: BYTE)
Remarks - Previously named StringConvert.
---------------------------------------------------------------------------}
TYPE
ArrayType = ARRAY[1..80] OF CHAR;
VAR
chars: ArrayType ABSOLUTE CharArrayP;
StrLen,
i : BYTE;
BEGIN
StrLen := Length(StrP);
StrP := StrP + CharStr(' ',Len - StrLen); {pad string with spaces to array Len}
FOR i := 1 TO Len DO
chars[i] := StrP[i];
{}END {StringToArray};
{}FUNCTION ArrayToString(VAR CharArrayP; start:WORD; Len:BYTE):STRING;
{+H
---------------------------------------------------------------------------
Purpose - Convert subelements of a character array, starting at position
START, into a string of length LEN.
Declaration - ArrayToString(VAR CharArrayP; start:WORD; Len:BYTE)
Result type - string.
Remarks - The user is responsible for determining that START+LEN does not
exceed the array bounds.
Revised - 1991.0613 (KSB) Wrote initial version.
---------------------------------------------------------------------------}
{$R-}
TYPE
ArrayType = ARRAY[1..1]OF CHAR;
VAR
chars: ArrayType ABSOLUTE CharArrayP;
s : STRING;
i : WORD;
BEGIN
FillChar(s,256,0);
FOR i := 1 TO Len DO
s[i] := chars[start+i-1];
s[0] := CHAR(Len);
ArrayToString := s;
{}END {ArrayToString};
{}FUNCTION StringToReal(s:STRING):REAL;
{+H
---------------------------------------------------------------------------
Purpose - Convert a string representation of a real number to a value.
Declaration - StringToReal(s:STRING)
Revised - 1992.0407 (KSB) Wrote initial version.
- 1992.0423 (KSB) Rewrote without reference to TP calls.
---------------------------------------------------------------------------}
VAR
r : REAL;
len : BYTE ABSOLUTE s;
c : INTEGER;
BEGIN
WHILE s[len] = ' ' DO
Dec(len);
Val(s,r,c);
IF c <> 0 THEN
r := 0;
StringToReal := r;
{}END {StringToReal};
{}FUNCTION DollarsToPennies(s:STRING):LongINT;
{+H
---------------------------------------------------------------------------
Purpose - Convert a string "$34.67" to 3467.
Declaration - DollarsToPennies(s:STRING)
Revised - 1992.0423 (KSB) Rewrote.
---------------------------------------------------------------------------}
VAR
r : REAL;
t : STRING;
L : BYTE ABSOLUTE s;
BEGIN
s := Trim(s);
IF s[1] = '$' THEN
Delete(s,1,1);
t := '';
WHILE (L>0) AND (s[1] IN ['0'..'9','.']) DO BEGIN
t := t + s[1];
Delete(s,1,1);
END {WHILE};
DollarsToPennies := Round(StringToReal(t)*100);
{}END {DollarsToPennies};
{------------------------------
{Pattern Matching}
{}FUNCTION Matches(s,pattern:STRING):BOOLEAN;
{+H
---------------------------------------------------------------------------
Purpose - If pattern is found in S then return true.
Declaration - Matches(s,pattern:STRING)
Rules - "a" matches A..Z, a..z
"9" matches 0..9
"8" matches 0..9 or trailing blanks.
Characters after 1st blank illegal
"^A" matches beginning of line
"^Z" matches end of line (not implemented)
Uppercase alpha char matches that char, case insensitive
Other characters map to themselves.
Revised - 1990.09xx (KSB) Wrote initial version.
- 1990.0920 (KSB) Added "8" rule.
- 1991.0825 (KSB) Revised "8" Rule to allow S strings shorter
than the pattern.
---------------------------------------------------------------------------}
CONST
mbeg = ^a;
mend = ^z;
alpha= 'a';
numbr= '9';
noblk= '8';
VAR
firstblank: BOOLEAN;
{}{}FUNCTION Match(s,pattern:STRING):BOOLEAN;
VAR
L : BYTE ABSOLUTE s;
m : BYTE ABSOLUTE pattern;
i : INTEGER;
ok : BOOLEAN;
BEGIN
Match := FALSE;
FOR i := 1 TO m DO BEGIN
CASE pattern[i] OF
'a' : ok := s[i] IN ['A'..'Z','a'..'z'];
'9' : ok := s[i] IN ['0'..'9'];
'8' :
BEGIN
IF L<i THEN BEGIN {1991.0825}
Match := TRUE;
Exit;
END {IF};
ok := s[i] IN ['0'..'9',' '];
IF ok AND (s[i]=' ') THEN BEGIN
ok := NOT firstBlank;
firstBlank := TRUE;
END {IF};
END {BEGIN};
^z : ok := L=Pred(i);
ELSE
ok := pattern[i]=UpCase(s[i]);
END {CASE};
IF NOT ok THEN
Exit;
END {FOR};
Match := TRUE;
{}{}END {Match};
VAR
L : BYTE ABSOLUTE s;
m : BYTE ABSOLUTE pattern;
i,j : INTEGER;
BEGIN
Matches := TRUE;
IF m=0 THEN
Exit;
Matches := FALSE;
IF L=0 THEN
Exit;
firstBlank := FALSE;
s := StUpCase(s);
IF pattern[1]= mbeg THEN BEGIN
Matches := Match(s,Copy(pattern,2,m));
Exit;
END ELSE BEGIN
IF L=m THEN BEGIN
Matches := Match(s,pattern);
Exit;
END ELSE BEGIN
i := L-m;
IF i<0 THEN
i := m; {1991.0825; was exit}
FOR j:= 1 TO i DO
IF Match(Copy(s,j,L),pattern) THEN BEGIN
Matches := TRUE;
Exit;
END {IF};
END {BEGIN};
END {BEGIN};
{}END {Matches};
{}FUNCTION IsAfter(s1,s2,s:STRING):BOOLEAN;
{+H
---------------------------------------------------------------------------
Purpose - Return true if S1 occurs after S2 in S.
Declaration - IsAfter(s1,s2,s:STRING)
Result type - boolean.
Remarks - S1, S2, and S are string-type expressions. If substring S1
occurs in the string S after the substring S2, the function
will return true.
---------------------------------------------------------------------------}
VAR
i,j : BYTE;
BEGIN
i := Pos(s1,s);
j := Pos(s2,s);
IF (i=0) OR (j=0) OR (i <= j) THEN
IsAfter := FALSE
ELSE
IsAfter := TRUE;
{}END {IsAfter};
{}FUNCTION IsBefore(s1,s2,s:STRING):BOOLEAN;
{+H
---------------------------------------------------------------------------
Purpose - Return true if S1 occurs before S2 in S.
Declaration - IsBefore(s1,s2,s:STRING)
Result type - boolean.
Remarks - S1, S2, and S are string-type expressions. If substring S1
occurs in the string S before the substring S2, the function
will return true.
---------------------------------------------------------------------------}
VAR
i,j : BYTE;
BEGIN
i := Pos(s1,s);
j := Pos(s2,s);
IF (i=0) OR (j=0) OR (i >= j) THEN
IsBefore:= FALSE
ELSE
IsBefore:= TRUE;
{}END {IsBefore};
{}FUNCTION Indented(s:STRING):BYTE;
{+H
---------------------------------------------------------------------------
Purpose - Returns number of leading white space characters in S.
Declaration - Indented(s:STRING)
Result type - byte.
Remarks - S is a string-type expression. The function returns the
number of leading white space characters.
---------------------------------------------------------------------------}
VAR
L : BYTE ABSOLUTE s;
i : BYTE;
BEGIN
i := 1;
WHILE (i < L) AND (s[i] IN [#0..#32]) DO
Inc(i);
Indented := Pred(i);
{}END {Indented};
{------------------------------
{Character testing}
{}FUNCTION IsLetter(c:CHAR):BOOLEAN;
{+H
---------------------------------------------------------------------------
Purpose - Returns T if c a letter.
Declaration - IsLetter(c:CHAR)
Result type - boolean.
---------------------------------------------------------------------------}
BEGIN
IsLetter := c IN ['A'..'Z','a'..'z'];
{}END {IsLetter};
{}FUNCTION IsLower(c:CHAR):BOOLEAN;
{+H
---------------------------------------------------------------------------
Purpose - Returns T if c an lowercase letter.
Declaration - IsLower(c:CHAR)
Result type - boolean.
---------------------------------------------------------------------------}
BEGIN
IsLower := c IN ['a'..'z'];
{}END {IsLower};
{}FUNCTION IsUpper(c:CHAR):BOOLEAN;
{+H
---------------------------------------------------------------------------
Purpose - Returns T if c an uppercase letter.
Declaration - IsUpper(c:CHAR)
Result type - boolean.
---------------------------------------------------------------------------}
BEGIN
IsUpper := c IN ['A'..'Z'];
{}END {IsUpper};
{*}
{}FUNCTION IsDigit(c:CHAR):BOOLEAN;
{+H
---------------------------------------------------------------------------
Purpose - Returns T if c is a digit.
Declaration - IsDigit(c:CHAR)
Result type - boolean.
---------------------------------------------------------------------------}
BEGIN
IsDigit := c IN ['0'..'9'];
{}END {IsDigit};
{}FUNCTION IsHexDigit(c:CHAR):BOOLEAN;
{+H
---------------------------------------------------------------------------
Purpose - Returns T if c is a hexidecimal digit.
Declaration - IsHexDigit(c:CHAR)
Result type - boolean.
---------------------------------------------------------------------------}
BEGIN
IsHexDigit := c IN ['0'..'9','A'..'F','a'..'f'];
{}END {IsHexDigit};
{*}
{}FUNCTION IsAlphaNum(c:CHAR):BOOLEAN;
{+H
---------------------------------------------------------------------------
Purpose - Returns T if c a letter or digit.
Declaration - IsAlphaNum(c:CHAR)
Result type - boolean.
---------------------------------------------------------------------------}
BEGIN
IsAlphaNum := c IN ['A'..'Z','a'..'z','0'..'9'];
{}END {IsAlphaNum};
{}FUNCTION IsAscii(c:CHAR):BOOLEAN;
{+H
---------------------------------------------------------------------------
Purpose - Returns T if c is in standard ASCII set.
Declaration - IsAscii(c:CHAR)
Result type - boolean.
---------------------------------------------------------------------------}
BEGIN
IsAscii := c IN [#000..#127];
{}END {IsAscii};
{}FUNCTION IsCntrl(c:CHAR):BOOLEAN;
{+H
---------------------------------------------------------------------------
Purpose - Returns T if c is a control character or delete.
Declaration - IsCntrl(c:CHAR)
Result type - boolean.
---------------------------------------------------------------------------}
BEGIN
IsCntrl := c IN [#0..#31,#127];
{}END {IsCntrl};
{}FUNCTION IsExtended(c:CHAR):BOOLEAN;
{+H
---------------------------------------------------------------------------
Purpose - Returns T if c is a member of the extended ASCII set.
Declaration - IsExtended(c:CHAR)
Result type - boolean.
---------------------------------------------------------------------------}
BEGIN
IsExtended := c IN [#128..#255];
{}END {IsExtended};
{}FUNCTION IsPrint(c:CHAR):BOOLEAN;
{+H
---------------------------------------------------------------------------
Purpose - Returns T if c is a printing character in the standard ASCII set.
Declaration - IsPrint(c:CHAR)
Result type - boolean.
---------------------------------------------------------------------------}
BEGIN
IsPrint := c IN [#032..#126];
{}END {IsPrint};
{}FUNCTION IsPunct(c:CHAR):BOOLEAN;
{+H
---------------------------------------------------------------------------
Purpose - Returns T if c is a punctuation character.
Declaration - IsPunct(c:CHAR)
Result type - boolean.
---------------------------------------------------------------------------}
BEGIN
IsPunct := NOT(IsAlphaNum(c) OR IsCntrl(c) OR IsExtended(c));
{}END {IsPunct};
{}FUNCTION IsSpace(c:CHAR):BOOLEAN;
{+H
---------------------------------------------------------------------------
Purpose - Returns T if c is a white space char. (tab, linefeed, vert.tab, formfeed, CR, space)
Declaration - IsSpace(c:CHAR)
Result type - boolean.
---------------------------------------------------------------------------}
BEGIN
IsSpace := c IN [#009..#013,#032];
{}END {IsSpace};
{------------------------------
{Other}
{}FUNCTION InSet(VAR someSet; VAR setMember):BOOLEAN;
{+H
---------------------------------------------------------------------------
Purpose - If SOMESET is not empty, InSet extracts the lowest set member
from the set and returns True. If SOMESET is empty, InSet
returns False.
Declaration - InSet(VAR someSet; VAR setMember)
Result type - boolean.
Warning - This function modifies its arguments, ie., it lacks idempotency.
Revised - 1991.0614 (KSB) Wrote initial version.
Example:
var chars : set of char; c : char;
begin
chars := ['A','E','I','O','U'];
while InSet(chars,c) do ...
end;
---------------------------------------------------------------------------}
TYPE
SetType = SET OF BYTE;
VAR
baseSet : SetType ABSOLUTE someSet;
mmbr : BYTE ABSOLUTE setMember;
BEGIN
InSet := FALSE;
mmbr := 255;
REPEAT
IF baseSet = [] THEN
Exit;
Inc(mmbr);
IF (mmbr IN baseSet) THEN BEGIN
baseSet := baseSet - [mmbr];
InSet := TRUE;
Exit;
END {IF};
UNTIL mmbr = 255;
{}END {InSet};
{}FUNCTION CountOf(s:STRING; cs:CharSet):BYTE;
{+H
---------------------------------------------------------------------------
Purpose - Count the number of CS characters in S.
Declaration - CountOf(s:STRING; cs:CharSet)
Result type - byte.
---------------------------------------------------------------------------}
VAR
L : BYTE ABSOLUTE s;
i : WORD;
count: WORD;
BEGIN
count := 0;
IF (cs <> []) THEN
FOR i := 1 TO L DO
IF s[i] IN cs THEN
Inc(count);
CountOf := count;
{}END {CountOf};
BEGIN
END {BEGIN}.